package com.wlf.admin.system.service;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HtmlUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.wlf.admin.common.dto.CacheKey;
import com.wlf.admin.common.dto.Const;
import com.wlf.admin.common.util.AjaxBean;
import com.wlf.admin.common.util.JSON;
import com.wlf.admin.system.domain.SysOrgan;
import com.wlf.admin.system.domain.SysUser;
import com.wlf.admin.system.mapper.SysOrganMapper;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@CacheConfig(cacheNames = CacheKey.organ)
@RequiredArgsConstructor
public class SysOrganService extends ServiceImpl<SysOrganMapper, SysOrgan> {
    public AjaxBean getList(SysOrgan organ) {
        List<SysOrgan> list = this.lambdaQuery()
                .like(StrUtil.isNotBlank(organ.getName()), SysOrgan::getName, organ.getName())
                .like(StrUtil.isNotBlank(organ.getOrganNo()), SysOrgan::getOrganNo, organ.getOrganNo())
                .list();
        ArrayList<SysOrgan> pOrgans = new ArrayList<>();
        list.forEach(i -> reverseOrgan(i, pOrgans));
        list.addAll(pOrgans);
        List<Tree<Long>> disabled = TreeUtil.build(list, 0L,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId());
                    tree.setParentId(treeNode.getPid());
                    tree.setWeight(treeNode.getSort());
                    tree.setName(treeNode.getName());
                    tree.putExtra("organNo", treeNode.getOrganNo());
                    tree.putExtra("status", treeNode.getStatus());
                    tree.putExtra("showChildren", treeNode.getShowChildren());
                    tree.putExtra("sort", treeNode.getSort());
                    tree.putExtra("remark", treeNode.getRemark());
                });
        return AjaxBean.getOkData(disabled).setCount((long) list.size()).setCode(0);
    }

    @Cacheable(key = "#id")
    public SysOrgan get(Long id) {
        return this.getById(id);
    }

    /**
     * 删除菜单
     */
    @CacheEvict(key = "#id")
    public AjaxBean del(Long id) {
        // 判断是否有子集，有的话禁止删除
        if (this.lambdaQuery().eq(SysOrgan::getPid, id).count() > 0) {
            return AjaxBean.getError("机构存在子集无法删除!");
        }
        return AjaxBean.getByBool(this.removeById(id));
    }


    public AjaxBean add(SysOrgan organ) {
        this.save(organ);
        return AjaxBean.getOkData(organ);
    }

    @CacheEvict(key = "#organ.id")
    public AjaxBean update(SysOrgan organ) {
        return AjaxBean.getByBool(this.updateById(organ));
    }


    /**
     * 根据用户查询该用户所拥有的所有机构
     * 一般用来做权限校验用
     */
    public List<SysOrgan> getOrganListByUserId(Long userId) {
        SysUser user = Db.getById(userId, SysUser.class);
        Long organId = user.getOrganId();
        List<SysOrgan> sysOrgans = new ArrayList<>();
        SysOrgan organ = SpringUtil.getBean(this.getClass()).get(organId);
        if (organ == null) {
            return sysOrgans;
        }
        // 如果展示子集则递归所有信息
        if (organ.getShowChildren()) {
            sysOrgans = this.getBaseMapper().recursionOrgan(organ.getId());
        } else {
            // 不展示子集则子只返回自己
            sysOrgans.add(organ);
        }

        return sysOrgans;
    }

    /**
     * 根据用户ID获取该用户拥有的机构Id
     */
    public List<Long> getOrganIdsByUserId(Long userId) {
        return SpringUtil.getBean(this.getClass())
                .getOrganListByUserId(userId).stream().map(SysOrgan::getId).collect(Collectors.toList());
    }


    /**
     * 获取登录用户拥有的机构信息
     */
    public List<SysOrgan> getOrganListByLoginUser() {
        return SpringUtil.getBean(this.getClass())
                .getOrganListByUserId(StpUtil.getLoginIdAsLong());
    }

    /**
     * 获取登录用户拥有的机构Id
     */
    public List<Long> getOrganIdsByLoginUser() {
        return getOrganIdsByUserId(StpUtil.getLoginIdAsLong());
    }

    /**
     * 下根据登录用户获取拉机构查询树结构
     */
    public List<Tree<String>> getTreeByLoginUser() {
        List<SysOrgan> organs = getOrganListByLoginUser();
        if (organs.isEmpty()) {
            return new ArrayList<>();
        }
        TreeNodeConfig tConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的
        tConfig.setIdKey("value");
        tConfig.setChildrenKey("children");
        tConfig.setNameKey("name");
        return TreeUtil.build(organs, organs.get(0).getPid() + "", tConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId().toString());
                    tree.setParentId(treeNode.getPid().toString());
                    tree.setWeight(treeNode.getSort());
                    tree.setName(treeNode.getName());
                    tree.putExtra("disabled", !treeNode.getStatus());
                });
    }

    /**
     * 功能描述: 获取登录用户所拥有机构树JSON字符串
     *
     * @author wlf 2024/1/23 17:31
     */
    public String getTreeByLoginUserJsonStr() {
        return JSON.toJSONString(getTreeByLoginUser());
    }


    /**
     * 功能描述: 向上递归直到根节点
     *
     * @author wlf 2023/9/5 10:14
     */
    private void reverseOrgan(SysOrgan organ, List<SysOrgan> organs) {
        organs.add(organ);
        SysOrgan pOrgan = SpringUtil.getBean(this.getClass()).get(organ.getPid());
        if (pOrgan != null) {
            reverseOrgan(pOrgan, organs);
        }
    }


    /**
     * 如果传空字符串，或者[]，则使用默认ID范围，如果默认ID范围为空，则返回[-1L]，查询不出数据
     * 接受前端传来的查询ID字符串，获取机构IDS,JSON字符串
     */
    public List<Long> getByIdsStr(String organIdsStr) {
        List<Long> organIds;
        if (StrUtil.isNotBlank(organIdsStr)) {
            List<Long> longList = JSON.parseArray(HtmlUtil.unescape(organIdsStr), Long.class);
            if (longList.isEmpty()) {
                organIds = this.getOrganIdsByLoginUser();
            } else {
                organIds = longList;
            }
        } else {
            organIds = this.getOrganIdsByLoginUser();
        }
        return organIds.isEmpty() ? ListUtil.of(-1L) : organIds;
    }

    /**
     * 功能描述: info页面所需数据
     *
     * @author wlf 2024/2/1 17:18
     */
    public Dict infoData(Long id) {
        @Data
        class Item {
            public Item(String title, String value, Boolean disabled) {
                this.title = title;
                this.value = value;
                this.disabled = disabled;
            }
            private String title;
            private String value;
            private Boolean disabled;
        }
        return Dict.create()
                .set("all", Db.lambdaQuery(SysUser.class).list()
                        .stream().map(i -> new Item(i.getName(), i.getId().toString(), i.getStatus().equals(Const.UserStatus.invalid.name()))).collect(Collectors.toList()))
                .set("organUser", Db.lambdaQuery(SysUser.class).eq(SysUser::getOrganId, id).list()
                        .stream().map(SysUser::getId).collect(Collectors.toList()))
                ;
    }
}
